--[[
-- @Author:	grayson
-- @DateTime: 2020-10-30 23:05:48
-- @Description: 客户端连接服务端使用

--]]


--local socket = require("skynet.socket")
local codecobj
local websocket = require "http.websocket"

--消息打包类
local ClientNet = class("ClientNet")


function ClientNet:ctor()
    self.fd = nil
    self.ip = nil
    self.port = nil
    self.msg_callbacks = {} --消息回调列表
    self.session = 1

    local server_config = g.getServerConf()
    local proto_config = server_config.proto
    codecobj = new("network.proto.codec", proto_config)
    --接收消息
    g.fork(function()
        while true do
            -- print(">>>M:recv_loop>>>")
            if self.fd then
                local ok, str, close_reason = pcall(websocket.read, self.fd)
                if ok and str then
                    self:receive(str)
                else
                    g.log:error("接收数据错误,关闭fd:", self.fd, str, close_reason)
                    self:close(self.fd, close_reason)
                end
                --websocket.ping( self.fd)
                g.sleep(100)
            else
                g.sleep(100)
            end
        end
    end)
end

----取大端2个字节
--function ClientNet:readShortBig( text ) --big endian
--    return text:byte(1)*256 + text:byte(2)
--end
--
----包长度2字节（skynet 规定头2个字节为包长度
--function ClientNet:unpackPackage(text)
--    local size = #text
--    if size < 2 then
--        return nil, text
--    end
--    local pack_size = self:readShortBig(text)
--    if size < pack_size + 2 then
--        return nil, text
--    end
--    local offset = 2
--    local msg = text:sub(offset + 1, offset + pack_size)
--    local last = text:sub(offset + 1 + pack_size)
--    return msg, last
--end

--连接socket
function ClientNet:connect(ip, port)
    local protocol = "ws"
    local url = string.format("%s://%s:%s/test_websocket", protocol, ip , port)
    if not ip or not port then
        print("ClientNet:connect ip port is nill___")
        return false
    end
    self.ip = ip
    self.port = port
    self.fd =  websocket.connect(url)
    if not self.fd then
        print("连接 "..ip..":"..port.."失败")
        return false
    end
    print("########连接"..ip..":"..port.."成功#########")
    return true
end

function ClientNet:receive(str)
    print("收到数据"..#str)
    local ok, u_msg = pcall(codecobj.cl_unpack_message, codecobj, str)
    if not ok then
        --解析消息错误
        g.log:error(u_msg)
        return
    end
    local ok , result = xpcall(g.dispatch.dispatchMessage, g.handle_err, g.dispatch, nil, nil, u_msg.cmd, u_msg.args)
    if ok then
        if result then
            --self.client_pack:send(fd, name, result, "response")
            return
        end
    else
        g.log:error(result)
        return
    end
    --g.log:info("msg receive no dispatch", tostring(u_msg))
end

function ClientNet:close(fd, close_reason)
    print("ClientNet:close fd:",self.fd)
    if self.fd then
        websocket.close(self.fd, close_reason)
    end
    self.fd = nil
    os.exit()
end

function ClientNet:send(msg_name, msg_body, conn_type)
    if not self.fd then
        local conn = self:connect(self.ip, self.port)
        if not conn then
            --连接失败            
            return
        end
    end
    --self.client_pack:clientSend(self.fd, msg_name, msg_body, conn_type)

    self.session = self.session + 1
    local message = {
        type = 1,
        cmd = msg_name,
        args = msg_body,
        session = self.session,
        ud = 0,--
    }
    local msg = codecobj:cl_pack_message(message)
    --local sz = string.len(msg)
    --local msg_tmp = string.pack(">H", sz) .. msg
    --if not msg_tmp or not sz then
    --    g.log:error('ClientPack:send msg_tmp=nil or sz=nil')
    --    return false
    --end
    ----g.log:fdebug("clientSend:%s, %s, %s ", msg_name, msg_tmp, sz)
    --for i=1, #msg_tmp do
    --    print(i, string.byte(msg_tmp,i))
    --end
    --msg_tmp = handshake:encrypt(msg_tmp)
    local ok, err = xpcall(websocket.write, debug.traceback, self.fd, msg)
    if not ok then
        g.log:error('ClientPack:send faild:', err)
        return false
    end
end


return ClientNet